/**
 * 
 */
package com.wolfpire.system.common.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.RequestKey;
import org.springframework.security.web.util.AntUrlPathMatcher;

import com.wolfpire.system.common.AuthorityUtils;
import com.wolfpire.system.model.Authority;
import com.wolfpire.system.service.AuthorityService;


/**
 * @author lihd
 *
 */
public class HibernateFilterInvocationSecurityMetadataSource implements
		FactoryBean<FilterInvocationSecurityMetadataSource> {
	
	@Resource private AuthorityService authorityService;

	@Override
	public FilterInvocationSecurityMetadataSource getObject() throws Exception {
		return new DefaultFilterInvocationSecurityMetadataSource(new AntUrlPathMatcher(), getResources());
	}
	
	protected LinkedHashMap<RequestKey, Collection<ConfigAttribute>> getResources(){
    	LinkedHashMap<RequestKey, Collection<ConfigAttribute>> resourceMap = new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>();
    	
    	List<Authority> resourceList = this.authorityService.list(null);
    	Map<Long, Authority> map = new HashMap<Long, Authority>();
        for (Authority authority : resourceList) {
        	if(StringUtils.isNotBlank(authority.getPath())){
        		String url = null;
                if(Authority.TYPE_MENU.equals(authority.getType())){
                	url = authority.getPath();
                }else if(Authority.TYPE_OPERATOR.equals(authority.getType())){
					Authority pa = AuthorityUtils.getParentAuth(resourceList, authority, map); 
							//this.findParent(resourceList, authority, map); 
//                			this.authorityService.get(authority.getParentId());
                	String menuPath = pa.getPath(); 
                	int index = menuPath.lastIndexOf("/");
                	// TODO:
                	if(index > -1){
                		url = menuPath.subSequence(0, index) + "/" + authority.getPath();
                	}else{
                		url = menuPath + "/" + authority.getPath();
                	}
                	
                }
                String role = "AUTH_" + authority.getId();
                
                RequestKey requestKey = new RequestKey(url);
                Collection<ConfigAttribute> attributes = resourceMap.get(requestKey);
                
                if (attributes == null) {
                	attributes = new HashSet<ConfigAttribute>();
                	resourceMap.put(requestKey, attributes);
                }
                
                attributes.add(new SecurityConfig(role));
        	}
            
        }
    	map = null;
    	return resourceMap;
    	
    }
	
	@Override
	public Class<FilterInvocationSecurityMetadataSource> getObjectType() {
		return FilterInvocationSecurityMetadataSource.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

}
